﻿using iSciences.Common;
using iSciences.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Search;
using Windows.Data.Xml.Dom;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Grid App template is documented at http://go.microsoft.com/fwlink/?LinkId=234226

namespace iSciences
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton Application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;


        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override async void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();                           
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    try
                    {
                        await SuspensionManager.RestoreAsync();
                    }
                    catch (SuspensionManagerException)
                    {
                    }
                }
                Window.Current.Content = rootFrame;
            }
            if (rootFrame.Content == null)
            {
                //show splash screen while data loading
                Window.Current.Content = new SplashScreen();
                Window.Current.Activate();

                //load data
                await AppData.Init();

                //update application notifications
                TileNotificationsQueue();

                //setting back the root frame
                Window.Current.Content = rootFrame;

                if (!rootFrame.Navigate(typeof(CategoriesPage), AppData.Categories))
                {
                    throw new Exception("Failed to create initial page");
                }
            }

            Window.Current.Activate();
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            try
            {
                var deferral = e.SuspendingOperation.GetDeferral();
                await SuspensionManager.SaveAsync();
                deferral.Complete();
            }
            catch (Exception)
            {
            }
            
            //save user data
            AppData.SerializeUser(AppData.CurrentUser);
        }

        //----------------------------------------------------------------------
        // SEARCHINGGG
        //----------------------------------------------------------------------
        protected async override void OnSearchActivated(SearchActivatedEventArgs args)
        {
            base.OnSearchActivated(args);

            //suggestion search events

            SearchPane.GetForCurrentView().SuggestionsRequested += SearchResultPage_SuggestionsRequested;
            SearchPane.GetForCurrentView().ResultSuggestionChosen += SearchResultPage_ResultSuggestionChosen;

            //Cerate new frame or get the existance
            UIElement rootframe = Window.Current.Content;

            if (rootframe != null && rootframe is Frame)
            {
                Frame frame = GetOrCreateFrame();
                //navigate to search page
                frame.Navigate(typeof(SearchResultPage), args.QueryText);
            }
            else
            {
                //Create new frame
                Frame frame = GetOrCreateFrame();

                //show splash screen while data loading
                Window.Current.Content = new SplashScreen();
                Window.Current.Activate();

                //load app data
                await AppData.Init();

                //setting back the root frame
                Window.Current.Content = frame;

                //navigate to search page
                frame.Navigate(typeof(SearchResultPage), args.QueryText);
            }
        }

        /// <summary>
        /// Inoked the user selects a result from search pane
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void SearchResultPage_ResultSuggestionChosen(SearchPane sender, SearchPaneResultSuggestionChosenEventArgs args)
        {
            string id = args.Tag.ToString();
            Article article = AppData.GetArticleById(id);
            Frame frame = GetOrCreateFrame();
            frame.Navigate(typeof(ArticleDetailPage), article);

        }

        void SearchResultPage_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
        {
            var deferral = args.Request.GetDeferral();
            //Suggestion 
            var suggestions = args.Request.SearchSuggestionCollection;
            suggestions.AppendQuerySuggestions(AppData.GetArticlesSuggestion(args.QueryText));

            //results
            List<Article> articles = AppData.SearchExactArticle(args.QueryText);
            if (articles.Count > 0)
            {
                suggestions.AppendSearchSeparator("Articles");
                foreach (var article in articles)
                {
                    Uri uri = new Uri(article.ImageUrl);
                    IRandomAccessStreamReference imageSource = RandomAccessStreamReference.CreateFromUri(uri);
                    suggestions.AppendResultSuggestion(article.Title, article.Title, article.UniqueId.ToString(), imageSource, string.Empty);
                }
            }

            deferral.Complete();
        }

        private Frame GetOrCreateFrame()
        {
            Frame frame;
            UIElement content = Window.Current.Content;

            if (content != null && content is Frame)
            {
                frame = content as Frame;
            }
            else
            {
                frame = new Frame();

                Window.Current.Content = frame;
                Window.Current.Activate();
            }

            return frame;
        }

        //-----------------------------------------------------------------
        // Notifications (pool de notifications pour la vignette principale
        //-----------------------------------------------------------------
        private void TileNotificationsQueue()
        {
            var articles = AppData.GetTopFiveArticles();
            TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);

            foreach (Article article in articles)
            {
                var tileTemplate = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideImageAndText02);
                var text = tileTemplate.GetElementsByTagName("text");
                text[0].AppendChild(tileTemplate.CreateTextNode(article.Title));
                text[1].AppendChild(tileTemplate.CreateTextNode(article.Subtitle));

                var images = tileTemplate.GetElementsByTagName("image");
                var image = images[0] as XmlElement;
                image.SetAttribute("src",article.ImageUrl); //"ms-appx:///" + person.Photo);

                //smal notif
                var normalTileTemplate = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareBlock);

                var textAttributesNormalTile = normalTileTemplate.GetElementsByTagName("text");
                textAttributesNormalTile[0].AppendChild(normalTileTemplate.CreateTextNode(article.Title));
                var normalImages = normalTileTemplate.GetElementsByTagName("image");
                var normalImage = images[0] as XmlElement;
                normalImage.SetAttribute("src", article.ImageUrl);

                // Merge
                var bindingNode = tileTemplate.ImportNode(normalTileTemplate.GetElementsByTagName("binding")[0], true);
                tileTemplate.GetElementsByTagName("visual")[0].AppendChild(bindingNode);

                TileNotification tileNotification = new TileNotification(tileTemplate);
                tileNotification.ExpirationTime = DateTime.Now.AddMinutes(15);

                TileUpdateManager.CreateTileUpdaterForApplication().Update(tileNotification);
            }
        }
    }
}
